﻿// Copyright (c) 2007-2020 西安交通信息投资营运有限公司 版权所有
// 作者:吕艳阳

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Windows.Forms;

namespace daemon
{
    public static class Helper
    {
        public static void Run(string[] args)
        {
            if (args == null || args.Length == 0) return;
            var map = ResolveStartupArguments(args);
            var cmd = ToStringOrEmpty(map["cmd"]);
            if (cmd == "restart") Restart(map);
            else if (cmd == "upgrade") Upgrade(map);
            else if (cmd == "kill") Kill(map);
        }

        private static void Restart(Dictionary<string, object> args)
        {
            Kill(args);
            var path = ToStringOrEmpty(args["path"]);

            args.Remove("processId");
            args.Remove("path");
            StartupByPath(path, args); //启动文件路径
        }

        private static void Upgrade(Dictionary<string, object> args)
        {
            Kill(args);

            var frmUpgradeProgresscs = new FrmUpgradeProgresscs(args);
            frmUpgradeProgresscs.ShowDialog();
        }

        private static void Kill(Dictionary<string, object> args)
        {
            var processId = ToStringOrEmpty(args["processId"]);
            KillByProcessId(processId);

            var processName = ToStringOrEmpty(args["processName"]);
            KillByProcessName(processName);

            Process p = null;
            try
            {
                p = Process.GetProcessById(int.Parse(processId));
                p.Kill();
            }
            catch
            {
                // ignored
            }
            finally
            {
                if (p != null && !p.HasExited)
                {
                    MessageBox.Show($"无法终止进程,进程ID={processId},进程名称={processName},请手动终止进程后重新运行程序");
                    System.Environment.Exit(0);
                }
            }
        }

        /// <summary>
        /// 杀死指定Id的进程
        /// </summary>
        /// <param name="processIdStr">进程Id</param>
        private static void KillByProcessId(string processIdStr)
        {
            if (!int.TryParse(processIdStr, out var processId)) return;
            try
            {
                Process p = Process.GetProcessById(processId);
                if (!p.CloseMainWindow())
                {
                    p.Kill();
                }
            }
            catch (Exception e)
            {
                Trace.TraceError(e.Message);
            }
        }

        /// <summary>
        /// 杀死指定名称的进程
        /// </summary>
        /// <param name="name">进程名称</param>
        private static void KillByProcessName(string name)
        {
            if (!string.IsNullOrEmpty(name)) return;
            try
            {
                foreach (Process p in Process.GetProcessesByName(name))
                {
                    if (!p.CloseMainWindow())
                    {
                        p.Kill();
                    }
                }
            }
            catch (Exception e)
            {
                Trace.TraceError(e.Message);
            }
        }

        /// <summary>
        /// 启动指定路径的程序
        /// </summary>
        /// <param name="path">启动程序路径</param>
        /// <param name="args">参数</param>
        public static void StartupByPath(string path, Dictionary<string, object> args = null)
        {
            try
            {
                Process.Start(path, ToStartupArguments(args));
            }
            catch (Exception e)
            {
                MessageBox.Show($"重启进程失败:path={path};args={args};msg={e.Message}");
                Environment.Exit(0);
            }
        }

        /// <summary>
        /// 解析启动参数为Map集合
        /// </summary>
        /// <param name="args">启动参数集合</param>
        public static Dictionary<string, object> ResolveStartupArguments(string[] args)
        {
            var map = new Dictionary<string, object>();
            if (args == null || args.Length == 0) return map;

            foreach (var item in args)
            {
                if (string.IsNullOrWhiteSpace(item)) continue;
                var argsArray = item.Split(new[] { '=' }, StringSplitOptions.RemoveEmptyEntries);
                if (argsArray.Length != 2) continue;
                var key = ToStringOrEmpty(argsArray[0]);
                var value = ToStringOrEmpty(argsArray[1]);
                map[key] = value;
            }
            return map;
        }

        /// <summary>
        /// 将Map集合转为启动参数字符串
        /// </summary>
        /// <param name="args">Map集合</param>
        public static string ToStartupArguments(Dictionary<string, object> args)
        {
            if (args == null || args.Count == 0) return string.Empty;
            var sb = new StringBuilder();
            foreach (var pair in args)
            {
                sb.Append($"{ToStringOrEmpty(pair.Key)}={ToStringOrEmpty(pair.Value)} ");
            }
            return sb.ToString();
        }

        /// <summary>
        /// 转为为字符串(如果对象为空,返回空字符串)
        /// </summary>
        /// <param name="obj">测试对象</param>
        /// <returns>>如果对象为空,返回空字符串</returns>
        public static string ToStringOrEmpty(object obj)
        {
            return obj == null ? string.Empty : obj.ToString();
        }
    }
}